"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const path = require("path");
const fse = require("fs-extra");
const fs = require("fs");
const tplCompileUtil = require("../util/tpl-compile-util");
const npmLoadUtil = require("../util/npm-load-util");
let express = require("express");
let router = express.Router();
let request = require("request");
let zlibUtil = require("@qianmi/x-site-common/util/zlib-util");
let tplUtil = require("@qianmi/x-site-common/util/template-util");
let _ = require("@qianmi/x-site-common/util/response-util");
let initService = require("../service/init-service");
let publishLogService = require("../mongoose/service/publish-log-service");
let loadUpdateService = require("../service/load-update-service");
let { ossClient } = loadUpdateService;
let exec = require("child_process").execSync;
//http://dong:3333/tpl/upload/resources
/**
 *
 * //qianmi-web.oss-cn-hangzhou.aliyuncs.com/x-site/developer/resources
 * 部署开发者静态资源, 如图片,JS CSS等文件 到阿里云
 * 路径为
 */
router.post("/upload/resources", function (req, res, next) {
    ossClient
        .putObjectAbsolute(new Buffer(req.body.fileContents), path.join("/x-site/developer/resources", req.body.uploadPath))
        .then(res => {
        console.log("上传开发者静态资源成功!!", res);
        _.resultSucess("OK");
    }, err => {
        console.log(err);
        _.resultfailure("error");
    });
});
let avaliableRepo = [
    "@qianmi/x-site-ui",
    "@qianmi/x-site-ui-pad",
    "@qianmi/x-site-ui-public-weixin",
    "@qianmi/x-site-ui-zhang",
    "@qianmi/x-site-ui-winter",
    "@qianmi/x-site-ui-marketing",
    "@qianmi/x-site-ui-platform",
    "@qianmi/x-site-ui-wechat",
    "@qianmi/x-site-ui-wang",
    "@qianmi/x-site-ui-weixin",
    "@qianmi/x-site-ui-d2p",
    "@qianmi/x-site-ui-d2p-mobile",
    "@qianmi/x-site-ui-goods-list",
    "@qianmi/x-site-ui-server",
    "@qianmi/x-site-ui-ehome",
    "@qianmi/x-site-ui-bm001",
    "@qianmi/x-site-ui-dong",
    "@qianmi/x-site-ui-rn",
    "@qianmi/x-site-ui-dong",
    "@qianmi/x-site-ui-article",
    "@qianmi/x-site-ui-base-bar",
    "@qianmi/x-site-ui-wxapp",
    "@qianmi/x-site",
    "@qianmi/x-site-ui-goods-desc",
    "@qianmi/ad-screen"
];
/**
 * 获取所有可用的Npm包
 */
router.all("/packages", function (req, res, next) {
    res.status(200).send(_.resultSucess(avaliableRepo));
});
let content = "/x-site/${env}/public/template-index/${platForm}-template-index.json";
let tplConfigPath = "/x-site/${env}/public/template-index/${platForm}-template-config.json";
let OssPrex = "/x-site/${env}/public/barRepo/";
let OssTplPrex = "/x-site/${env}/public/buildTemplate/";
//http://dong:3333/tpl/reBuild
router.all("/buildAll", function (req, res, next) {
    (async () => {
        await _syncOtherTemplate({
            envCode: req.body.envCode,
            distDir: path.join(__dirname, "../temp")
        });
        res.status(200).send(_.resultSucess("OK"));
    })();
});
//http://dong:3333/tpl/deploy
router.all("/deploy", function (req, res, next) {
    (async () => {
        try {
            let user = req.session.user;
            let username = user && user.username ? user.username : "默默的部署了";
            let name = req.body.name;
            let version = req.body.version;
            let envCode = req.body.envCode;
            let distDir = path.join(__dirname, "../temp");
            let publishTime = getLocalTime(new Date().getTime());
            if (name === "@qianmi/x-site") {
                await initService.initActiveXsite(version);
                //记录部署历史
                await publishLogService.addPublishLog({
                    envCode: "test",
                    version,
                    username,
                    publishTime,
                    projectName: name,
                    operation: "deploy",
                    status: true
                });
                res.status(200).send(_.resultSucess("OK"));
            }
            else if (envCode === "prod" && version.indexOf("RELEASE") < 0) {
                res.send({ result: "warn", message: "线上版本必须部署RELEASE版本" });
            }
            else if (envCode === "test" || (user && user.username === "admin")) {
                let status = await _dealNpmPackage({ name, version, envCode, distDir });
                //记录部署历史
                await publishLogService.addPublishLog({
                    envCode,
                    version,
                    username,
                    status,
                    publishTime,
                    projectName: name,
                    operation: "deploy"
                });
                //同步模板
                if (req.body.syncTemplate) {
                    await _syncOtherTemplate({ version, name, envCode, distDir });
                }
                if (status) {
                    res.status(200).send(_.resultSucess("OK"));
                }
                else {
                    res.status(500).send(_.resultfailure("error"));
                }
            }
            else {
                res.send({ result: "login", message: "您没有权限部署该环境" });
            }
        }
        catch (err) {
            console.log(err);
            res.status(500).send(_.resultfailure("error"));
        }
    })();
});
/**
 * 其他模板
 * @param envCode   环境信息
 * @param distDir   临时目录
 * @param name      模板项目名称 可选的 如果不传则同步所有的模板 .
 * @param version   项目版本 可选的
 * @returns {Promise<boolean>}
 * @private
 */
async function _syncOtherTemplate(syncOtherTemplateParams) {
    let { envCode, distDir, name, version } = syncOtherTemplateParams;
    console.log("开始同步其它项目模板。。。");
    let { pcTplConfig, weixinTplConfig, appTplConfig } = await loadTplConfig({
        envCode
    });
    let allTplIndex = pcTplConfig.concat(weixinTplConfig).concat(appTplConfig);
    let _OssTplPrex = OssTplPrex.replace("${env}", envCode);
    for (let i = 0; i < allTplIndex.length; i++) {
        let templateConfig = allTplIndex[i];
        try {
            let str = JSON.stringify(templateConfig);
            // 如果模板中存在部署项目的模板则同步
            let isHit = false;
            //判断是否要同步此模板
            if (name && version) {
                console.log("仅同步引用", name, version, "的模板");
                //遍历用户所传的模板，这些模板不需要同步
                let widgetHead = name.split("/")[1] + "/";
                let userTplPath = path.join(distDir, "./" + name + "/dist/templateIndex.json");
                let userTplJson = fse.readJsonSync(userTplPath);
                let userTplIndex = {};
                for (let j = 0; j < userTplJson.length; j++) {
                    userTplIndex[userTplJson[j].templateName] = j + 1;
                }
                if (str.indexOf(widgetHead) >= 0 &&
                    !userTplIndex[templateConfig.templateName]) {
                    isHit = true;
                }
            }
            else {
                console.log("同步所有模板");
                isHit = true;
            }
            if (isHit) {
                let { templateJs, templateCss } = await tplCompileUtil.generateTemplateConfigContent({
                    projectName: name,
                    templateConfig,
                    distDir,
                    envCode
                });
                if (templateJs) {
                    let _content = ";//模板同步于 " +
                        name +
                        " : " +
                        version +
                        ";\n" +
                        templateJs.toString();
                    await ossClient.putObjectAbsolute(new Buffer(_content, "UTF-8"), _OssTplPrex + templateConfig.templateName + ".js");
                    await ossClient.putObjectAbsolute(new Buffer(templateCss, "UTF-8"), _OssTplPrex + templateConfig.templateName + ".css");
                }
            }
        }
        catch (err) {
            console.error("模板同步失败::", templateConfig.templateName, err.stack);
            throw err;
        }
    }
    //删除本地缓存文件
    let system = process.platform;
    if (system === "win32") {
        exec('rd /s /q "' + path.join(__dirname, "../temp/dist/") + '"');
    }
    else {
        exec('rm -rf "' + path.join(__dirname, "../temp/dist/") + '"');
    }
    console.log("已完成同步其它项目模板。。。");
    return true;
}
/**
 * 加载指定版本的模板包.
 * @param version
 * @param name
 * @param distDir
 * @param envCode
 * @returns {Promise<boolean>}
 * @private
 */
async function _dealNpmPackage({ version, name, distDir, envCode }) {
    let _OssPrex = OssPrex.replace("${env}", envCode);
    let _OssTplPrex = OssTplPrex.replace("${env}", envCode);
    //下载NPM包. 先验证s本地temp中是否有. 如果有就不加载 了.. 如果没有就去加载..
    //step1 :
    let { npmPackageDir } = await npmLoadUtil.loadNpmPackage({
        version,
        name,
        distDir
    });
    //上传相应的bar文件与模板文件到相应的环境中去..
    console.log("npmPackage   Dir", npmPackageDir);
    let _top = path.join(npmPackageDir, "dist");
    let widgetBarIndex = fse.readJsonSync(path.join(_top, "barIndex.json"));
    //上传barIndex.json到相应的环境中去
    widgetBarIndex.version = version;
    let barIndexPath = _OssPrex + name.slice(8) + "/barIndex.json";
    await ossClient.putObjectAbsolute(new Buffer(JSON.stringify(widgetBarIndex)), barIndexPath);
    let widgetNsArray = [];
    for (let widgetNs in widgetBarIndex) {
        try {
            let path1 = path.join(_top, "barRepo", widgetNs + ".js");
            widgetNsArray.push(widgetNs);
            let isok = await isFileReadAble(path1);
            if (isok) {
                await ossClient.putObjectAbsolute(path1, _OssPrex + widgetNs + ".js");
            }
            let path2 = path.join(_top, "barRepo", widgetNs + "-p.js");
            isok = await isFileReadAble(path2);
            if (isok) {
                await ossClient.putObjectAbsolute(path2, _OssPrex + widgetNs + "-p.js");
            }
            let path3 = path.join(_top, "barRepo", widgetNs + ".css");
            isok = await isFileReadAble(path3);
            if (isok) {
                await ossClient.putObjectAbsolute(path3, _OssPrex + widgetNs + ".css");
            }
        }
        catch (err) {
            console.log(err);
            return false;
        }
    }
    try {
        await notifyRoachBarCache({ envCode, widgetNsArray });
    }
    catch (err) { }
    try {
        let tplConfExists = fse.existsSync(path.join(_top, "templateConfig.json"));
        if (!tplConfExists) {
            return true;
        }
        let templateIndex = fse.readJsonSync(path.join(_top, "templateIndex.json"));
        let templateConfig = tplConfExists
            ? fse.readJsonSync(path.join(_top, "templateConfig.json"))
            : [];
        //将数据写入数据库
        let commandPath = path.join(__dirname, "../service/templateinfo2db.js");
        let command = `node --harmony ${commandPath} ${envCode} ${path.join(_top, "templateConfig.json")}`;
        console.log("模板数据入库==============>\n" + command);
        let c = require("child_process").exec(command);
        c.stdout.on("data", function (s) {
            console.log(s.toString());
        });
        c.stdout.on("end", function () {
            console.log(" done");
        });
        let { pcTplIndex, weixinTplIndex, appTplIndex } = await loadTplIndex({
            envCode
        });
        let { pcTplConfig, weixinTplConfig, appTplConfig } = await loadTplConfig({
            envCode
        });
        //上传模板JS与CSS
        for (let i = 0, ilen = templateIndex.length; i < ilen; i++) {
            let tplInfo = templateIndex[i];
            let tplContent = await getFileContent({
                filePath: path.join(_top, tplInfo.jsFile)
            });
            let _content = ";//版本号：" + version + ";\n" + tplContent.toString();
            await ossClient.putObjectAbsolute(new Buffer(_content, "UTF-8"), _OssTplPrex + tplInfo.templateName + ".js");
            await ossClient.putObjectAbsolute(path.join(_top, tplInfo.cssFile), _OssTplPrex + tplInfo.templateName + ".css");
        }
        pcTplIndex = _dealPlatFormIndex({
            userTplIndex: templateIndex,
            platFormTplIndex: pcTplIndex,
            platForm: "pc",
            envCode
        });
        weixinTplIndex = _dealPlatFormIndex({
            userTplIndex: templateIndex,
            platFormTplIndex: weixinTplIndex,
            platForm: "weixin",
            envCode
        });
        appTplIndex = _dealPlatFormIndex({
            userTplIndex: templateIndex,
            platFormTplIndex: appTplIndex,
            platForm: "app",
            envCode
        });
        await uploadTplIndex({ pcTplIndex, weixinTplIndex, appTplIndex, envCode });
        //模板完整信息索引文件
        if (templateConfig.length > 0) {
            pcTplConfig = _dealPlatFormConfig({
                userTplConfig: templateConfig,
                platFormTplConfig: pcTplConfig,
                platForm: "pc",
                envCode
            });
            weixinTplConfig = _dealPlatFormConfig({
                userTplConfig: templateConfig,
                platFormTplConfig: weixinTplConfig,
                platForm: "weixin",
                envCode
            });
            appTplConfig = _dealPlatFormConfig({
                userTplConfig: templateConfig,
                platFormTplConfig: appTplConfig,
                platForm: "app",
                envCode
            });
            await uploadTplConfig({
                pcTplConfig,
                weixinTplConfig,
                appTplConfig,
                envCode
            });
        }
        return true;
    }
    catch (err) {
        console.log(err);
        return false;
    }
}
async function notifyRoachBarCache({ envCode, widgetNsArray }) {
    let host;
    if (envCode === "test") {
        host = [
            "http://172.21.34.174:3002",
            "http://172.21.34.41:3002",
            "http://172.19.67.186:3002",
            "http://172.19.68.102:3002",
            "http://172.21.33.38:3002",
            "http://172.19.71.144:3002"
        ];
    }
    else if (envCode === "dong") {
        host = ["http://127.0.0.1:3002"];
    }
    else if (envCode === "gray") {
        host = ["http://172.17.16.72:3002"];
    }
    else if (envCode === "prod") {
        host = ["http://172.17.9.65:3002"];
    }
    for (let i = 0, ilen = host.length; i < ilen; i++) {
        console.log("通知小强清理bar缓存:", host[i]);
        let widgetNSArrayGzip = await zlibUtil.gzip(JSON.stringify(widgetNsArray));
        request.post(host[i] + "/widget/update", { form: { widgetNSArrayGzip } }, function (err) {
            if (err) {
                console.log("通知小强失败");
            }
        });
    }
}
let platForms = ["pc", "weixin", "app"];
//修改相应环境的模板信息
async function loadTplIndex({ envCode }) {
    try {
        let _content = content.replace("${env}", envCode);
        let response = await ossClient.getObjectAbsolute(_content.replace("${platForm}", "pc"));
        let pcTplIndex = JSON.parse(response.content.toString());
        response = await ossClient.getObjectAbsolute(_content.replace("${platForm}", "weixin"));
        let weixinTplIndex = JSON.parse(response.content.toString());
        response = await ossClient.getObjectAbsolute(_content.replace("${platForm}", "app"));
        let appTplIndex = JSON.parse(response.content.toString());
        return { pcTplIndex, weixinTplIndex, appTplIndex };
    }
    catch (err) {
        console.log(err);
    }
    return { pcTplIndex: [], weixinTplIndex: [], appTplIndex: [] };
}
async function loadTplConfig({ envCode }) {
    let _path = tplConfigPath.replace("${env}", envCode);
    let pcTplConfig = [];
    let weixinTplConfig = [];
    let appTplConfig = [];
    let response;
    try {
        response = await ossClient.getObjectAbsolute(_path.replace("${platForm}", "pc"));
        pcTplConfig = JSON.parse(response.content.toString());
        response = await ossClient.getObjectAbsolute(_path.replace("${platForm}", "weixin"));
        weixinTplConfig = JSON.parse(response.content.toString());
        response = await ossClient.getObjectAbsolute(_path.replace("${platForm}", "app"));
        appTplConfig = JSON.parse(response.content.toString());
    }
    catch (err) {
        console.log(err);
    }
    return { pcTplConfig, weixinTplConfig, appTplConfig };
}
/**
 * 上传模板JSON 与JS文件 .. 并在本地建一个备份 ..
 * @param pcTplIndex
 * @param weixinTplIndex
 * @param appTplIndex
 */
async function uploadTplIndex({ pcTplIndex, weixinTplIndex, appTplIndex, envCode }) {
    let _content = content.replace("${env}", envCode);
    fse.outputJsonSync(path.join(__dirname, "../public/template-index/pc-template-index.json"), pcTplIndex);
    fse.outputJsonSync(path.join(__dirname, "../public/template-index/weixin-template-index.json"), weixinTplIndex);
    fse.outputJsonSync(path.join(__dirname, "../public/template-index/app-template-index.json"), appTplIndex);
    await ossClient.putObjectAbsolute(new Buffer(JSON.stringify(pcTplIndex)), _content.replace("${platForm}", "pc"));
    await ossClient.putObjectAbsolute(new Buffer(JSON.stringify(weixinTplIndex)), _content.replace("${platForm}", "weixin"));
    await ossClient.putObjectAbsolute(new Buffer(JSON.stringify(appTplIndex)), _content.replace("${platForm}", "app"));
    await ossClient.putObjectAbsolute(new Buffer(tplUtil.transfertpIndex2JsFile(pcTplIndex)), _content.replace("${platForm}", "pc").replace(".json", ".js"));
    await ossClient.putObjectAbsolute(new Buffer(tplUtil.transfertpIndex2JsFile(weixinTplIndex)), _content.replace("${platForm}", "weixin").replace(".json", ".js"));
    await ossClient.putObjectAbsolute(new Buffer(tplUtil.transfertpIndex2JsFile(appTplIndex)), _content.replace("${platForm}", "app").replace(".json", ".js"));
    //上传到阿里云去..
}
//上传模板完整信息索引文件到阿里云
async function uploadTplConfig({ pcTplConfig, weixinTplConfig, appTplConfig, envCode }) {
    let _path = tplConfigPath.replace("${env}", envCode);
    await ossClient.putObjectAbsolute(new Buffer(JSON.stringify(pcTplConfig)), _path.replace("${platForm}", "pc"));
    await ossClient.putObjectAbsolute(new Buffer(JSON.stringify(weixinTplConfig)), _path.replace("${platForm}", "weixin"));
    await ossClient.putObjectAbsolute(new Buffer(JSON.stringify(appTplConfig)), _path.replace("${platForm}", "app"));
}
/**
 *
 * @param userTplIndex
 * @param platFormTplIndex
 * @private
 */
function _dealPlatFormIndex({ userTplIndex, platFormTplIndex, platForm, envCode }) {
    let templateCode2Index = {};
    for (let i = 0, ilen = userTplIndex.length; i < ilen; i++) {
        templateCode2Index[userTplIndex[i].templateName] = i;
    }
    let toDelTemplateIndex = -1;
    for (let i = 0, ilen = platFormTplIndex.length; i < ilen; i++) {
        if (platFormTplIndex[i].templateName === "first-article") {
            toDelTemplateIndex = i;
            break;
        }
    }
    if (toDelTemplateIndex !== -1) {
        platFormTplIndex.splice(toDelTemplateIndex, 1);
    }
    let platFormTpl2Index = {};
    for (let i = 0, ilen = platFormTplIndex.length; i < ilen; i++) {
        platFormTpl2Index[platFormTplIndex[i].templateName] = i;
    }
    for (let i = 0, ilen = userTplIndex.length; i < ilen; i++) {
        if (userTplIndex[i].platForm === platForm) {
            let jsFile = "//qianmi-web.oss-cn-hangzhou.aliyuncs.com/x-site/" +
                envCode +
                "/public/buildTemplate/" +
                userTplIndex[i].templateName +
                ".js", cssFile = "//qianmi-web.oss-cn-hangzhou.aliyuncs.com/x-site/" +
                envCode +
                "/public/buildTemplate/" +
                userTplIndex[i].templateName +
                ".css";
            if (platFormTpl2Index[userTplIndex[i].templateName]) {
                platFormTplIndex[platFormTpl2Index[userTplIndex[i].templateName]].detailInfo =
                    userTplIndex[i].detailInfo;
                platFormTplIndex[platFormTpl2Index[userTplIndex[i].templateName]].templateName_cn =
                    userTplIndex[i].templateName_cn;
                platFormTplIndex[platFormTpl2Index[userTplIndex[i].templateName]].updateTime =
                    userTplIndex[i].updateTime;
                platFormTplIndex[platFormTpl2Index[userTplIndex[i].templateName]].isShow =
                    userTplIndex[i].isShow;
                platFormTplIndex[platFormTpl2Index[userTplIndex[i].templateName]].platForm =
                    userTplIndex[i].platForm;
                platFormTplIndex[platFormTpl2Index[userTplIndex[i].templateName]].pageType =
                    userTplIndex[i].pageType;
                platFormTplIndex[platFormTpl2Index[userTplIndex[i].templateName]].pageCode =
                    userTplIndex[i].pageCode;
                platFormTplIndex[platFormTpl2Index[userTplIndex[i].templateName]].barMap =
                    userTplIndex[i].barMap;
                platFormTplIndex[platFormTpl2Index[userTplIndex[i].templateName]].styleType =
                    userTplIndex[i].styleType;
                platFormTplIndex[platFormTpl2Index[userTplIndex[i].templateName]].acceptStyles =
                    userTplIndex[i].acceptStyles;
                platFormTplIndex[platFormTpl2Index[userTplIndex[i].templateName]].jsFile = jsFile;
                platFormTplIndex[platFormTpl2Index[userTplIndex[i].templateName]].cssFile = cssFile;
            }
            else {
                platFormTplIndex.push(Object.assign({}, userTplIndex[i], { jsFile, cssFile }));
            }
        }
    }
    return platFormTplIndex;
}
function _dealPlatFormConfig({ userTplConfig, platFormTplConfig, platForm, envCode }) {
    let templateCode2Index = {};
    for (let i = 0, ilen = userTplConfig.length; i < ilen; i++) {
        templateCode2Index[userTplConfig[i].templateName] = i;
    }
    let platFormTpl2Index = {};
    for (let i = 0, ilen = platFormTplConfig.length; i < ilen; i++) {
        platFormTpl2Index[platFormTplConfig[i].templateName] = i;
    }
    for (let i = 0, ilen = userTplConfig.length; i < ilen; i++) {
        if (userTplConfig[i].platForm === platForm) {
            let jsFile = "//qianmi-web.oss-cn-hangzhou.aliyuncs.com/x-site/" +
                envCode +
                "/public/buildTemplate/" +
                userTplConfig[i].templateName +
                ".js", cssFile = "//qianmi-web.oss-cn-hangzhou.aliyuncs.com/x-site/" +
                envCode +
                "/public/buildTemplate/" +
                userTplConfig[i].templateName +
                ".css";
            let tplConfig = Object.assign({}, userTplConfig[i], { jsFile, cssFile });
            if (platFormTpl2Index[userTplConfig[i].templateName]) {
                platFormTplConfig[platFormTpl2Index[userTplConfig[i].templateName]] = tplConfig;
            }
            else {
                platFormTplConfig.push(tplConfig);
            }
        }
    }
    return platFormTplConfig;
}
/**
 * 文件 是否可读 , 如果文件不存在 , 也当做不可读
 * @param filePath
 * @return {Promise}
 */
function isFileReadAble(filePath) {
    return new Promise((resolve, reject) => {
        fs.access(filePath, fs.constants.R_OK, err => {
            if (err) {
                resolve(false);
            }
            else {
                resolve(true);
            }
            // console.log(err ? 'no access!' : 'can read/write');
        });
    });
}
function getFileContent({ filePath }) {
    return new Promise((resolve, reject) => {
        fs.readFile(filePath, (err, data) => {
            if (err)
                throw err;
            resolve(data);
        });
    });
}
function getLocalTime(timestamp) {
    let date = new Date(timestamp);
    let Y = date.getFullYear() + "-";
    let M = (date.getMonth() + 1 < 10
        ? "0" + (date.getMonth() + 1)
        : date.getMonth() + 1) + "-";
    let D = date.getDate() + " ";
    let h = date.getHours() + ":";
    let m = date.getMinutes() + ":";
    let s = date.getSeconds();
    return Y + M + D + h + m + s;
}
module.exports = router;
